#ifndef __M_LOG_H__
#define __M_LOG_H__
// 引入必要的工具类和组件头文件
#include "util.hpp"          // 通用工具类
#include "level.hpp"         // 日志级别定义
#include "message.hpp"       // 日志消息结构
#include "formatter.hpp"     // 日志格式化器
#include "sink.hpp"          // 日志输出目标(落地)
#include "looper.hpp"        // 异步日志循环器
// 标准库依赖
#include <vector>
#include <list>
#include <atomic>
#include <unordered_map>
#include <cstdarg>           // 可变参数支持
#include <type_traits>       // 类型检查工具


namespace zdflog{
// 前向声明同步/异步日志器
class SyncLogger;
class AsyncLogger;

/**
 * @brief 日志器基类，定义日志器核心接口和通用属性
 */
class Logger {
    public:
        /**
         * @brief 日志器类型枚举
         */
        enum class Type {
            LOGGER_SYNC = 0,  // 同步日志器：日志输出阻塞调用线程
            LOGGER_ASYNC      // 异步日志器：日志输出由后台线程处理
        };

        using ptr = std::shared_ptr<Logger>;  // 智能指针类型定义，简化内存管理

        /**
         * @brief 构造函数
         * @param name 日志器名称
         * @param formatter 日志格式化器
         * @param sinks 日志输出目标集合
         * @param level 日志输出级别阈值(默认DEBUG)
         */
        Logger(const std::string &name, 
            Formatter::ptr formatter,
            std::vector<LogSink::ptr> &sinks, 
            LogLevel::value level = LogLevel::value::DEBUG): 
            _name(name),  _level(level), _formatter(formatter),
            _sinks(sinks.begin(), sinks.end()){
        }

        /**
         * @brief 获取日志器名称
         * @return 日志器名称字符串
         */
        std::string loggerName() { return _name; }

        /**
         * @brief 获取当前日志级别阈值
         * @return 日志级别枚举值
         */
        LogLevel::value loggerLevel() { return _level; }

        /**
         * @brief DEBUG级别日志输出接口(可变参数)
         * @param file 调用文件路径
         * @param line 调用行号
         * @param fmt 日志格式字符串
         * @param ... 可变参数列表
         */
        void debug(const char *file, size_t line, const char *fmt, ...) {
            // 检查当前级别是否需要输出
            if (shouldLog(LogLevel::value::DEBUG) == false) {
                return ;
            }
            va_list al;
            va_start(al, fmt);          // 初始化可变参数列表
            log(LogLevel::value::DEBUG, file, line, fmt, al);  // 调用底层日志函数
            va_end(al);                 // 清理可变参数列表
        }

        /**
         * @brief INFO级别日志输出接口(可变参数)
         * 功能同debug，级别为INFO
         */
        void info(const char *file, size_t line, const char *fmt, ...) {
            if (shouldLog(LogLevel::value::INFO) == false) return ;
            va_list al;
            va_start(al, fmt);
            log(LogLevel::value::INFO, file, line, fmt, al);
            va_end(al);
        }

        /**
         * @brief WARN级别日志输出接口(可变参数)
         * 功能同debug，级别为WARN
         */
        void warn(const char *file, size_t line, const char *fmt, ...) {
            if (shouldLog(LogLevel::value::WARN) == false) return ;
            va_list al;
            va_start(al, fmt);
            log(LogLevel::value::WARN, file, line, fmt, al);
            va_end(al);
        }

        /**
         * @brief ERROR级别日志输出接口(可变参数)
         * 功能同debug，级别为ERROR
         */
        void error(const char *file, size_t line, const char *fmt, ...) {
            if (shouldLog(LogLevel::value::ERROR) == false) return ;
            va_list al;
            va_start(al, fmt);
            log(LogLevel::value::ERROR, file, line, fmt, al);
            va_end(al);
        }

        /**
         * @brief FATAL级别日志输出接口(可变参数)
         * 功能同debug，级别为FATAL
         */
        void fatal(const char *file, size_t line, const char *fmt, ...) {
            if (shouldLog(LogLevel::value::FATAL) == false) return ;
            va_list al;
            va_start(al, fmt);
            log(LogLevel::value::FATAL, file, line, fmt, al);
            va_end(al);
        }

        /**
         * @brief 日志器构建器基类，用于通过Builder模式构造日志器
         */
        class Builder {
            public:
                using ptr = std::shared_ptr<Builder>;  // 构建器智能指针

                /**
                 * @brief 构造函数，初始化默认参数
                 */
                Builder():_level(LogLevel::value::DEBUG), 
                    _logger_type(Logger::Type::LOGGER_SYNC) {}

                /**
                 * @brief 设置日志器名称
                 * @param name 日志器名称
                 */
                void buildLoggerName(const std::string &name) { _logger_name = name; }

                /**
                 * @brief 设置日志级别阈值
                 * @param level 日志级别
                 */
                void buildLoggerLevel(LogLevel::value level) { _level = level; }

                /**
                 * @brief 设置日志器类型(同步/异步)
                 * @param type 日志器类型枚举
                 */
                void buildLoggerType(Logger::Type type) { _logger_type = type; }

                /**
                 * @brief 通过格式字符串设置日志格式化器
                 * @param pattern 日志格式字符串
                 */
                void buildFormatter(const std::string pattern) { _formatter = std::make_shared<Formatter>(pattern); }

                /**
                 * @brief 通过已有格式化器指针设置日志格式化器
                 * @param formatter 格式化器智能指针
                 */
                void buildFormatter(const Formatter::ptr &formatter) { _formatter = formatter; }

                /**
                 * @brief 构建日志输出目标(Sink)
                 * @tparam SinkType Sink类型(如StdoutSink、FileSink等)
                 * @tparam Args 构造Sink所需的参数类型
                 * @param ... 构造Sink的参数
                 */
                template<typename SinkType, typename ...Args>
                void buildSink(Args &&...args) { 
                    // 通过Sink工厂创建Sink实例并添加到列表
                    auto sink = SinkFactory::create<SinkType>(std::forward<Args>(args)...);
                    _sinks.push_back(sink); 
                }

                /**
                 * @brief 纯虚函数，构建日志器实例
                 * @return 日志器智能指针
                 */
                virtual Logger::ptr build() = 0;

            protected:
                Logger::Type _logger_type;       // 日志器类型
                std::string _logger_name;        // 日志器名称
                LogLevel::value _level;          // 日志级别阈值
                Formatter::ptr _formatter;       // 日志格式化器
                std::vector<LogSink::ptr> _sinks;// 日志输出目标集合
        };

    protected:
        /**
         * @brief 检查当前级别是否需要输出日志
         * @param level 待检查的日志级别
         * @return 是否需要输出(true/false)
         */
        bool shouldLog(LogLevel::value level) { return level >= _level; }

        /**
         * @brief 底层日志处理函数(接收可变参数列表)
         * @param level 日志级别
         * @param file 调用文件路径
         * @param line 调用行号
         * @param fmt 日志格式字符串
         * @param al 可变参数列表
         */
        void log(LogLevel::value level, const char *file, size_t line, const char *fmt, va_list al) {
            char *buf;
            std::string msg;
            // 使用vasprintf格式化日志消息
            int len = vasprintf(&buf, fmt, al);
            if (len < 0) {
                msg = "格式化日志消息失败！！";  // 格式化失败时的错误提示
            }else {
                msg.assign(buf, len);  // 格式化成功则保存消息
                free(buf);             // 释放vasprintf分配的内存
            }
            // 构造日志消息对象(包含名称、文件、行号、内容、级别)
            LogMsg lm(_name, file, line, std::move(msg), level);
            // 格式化日志消息
            std::stringstream ss;
            _formatter->format(ss, lm);
            // 调用具体的日志输出实现(同步/异步)
            logIt(std::move(ss.str()));
        }

        /**
         * @brief 纯虚函数，日志输出的具体实现(由子类实现)
         * @param msg 格式化后的日志字符串
         */
        virtual void logIt(const std::string &msg) = 0;

    protected:
        std::mutex _mutex;                       // 同步锁(保护多线程操作)
        std::string _name;                       // 日志器名称
        Formatter::ptr _formatter;               // 日志格式化器
        std::atomic<LogLevel::value> _level;     // 日志级别阈值(原子变量，支持线程安全读写)
        std::vector<LogSink::ptr> _sinks;        // 日志输出目标集合
};

/**
 * @brief 同步日志器实现类
 * 特点：日志输出操作在调用线程中执行，会阻塞调用者直到输出完成
 */
class SyncLogger : public Logger {
    public:
        using ptr = std::shared_ptr<SyncLogger>;  // 同步日志器智能指针

        /**
         * @brief 构造函数
         * 参数含义同Logger基类
         */
        SyncLogger(const std::string &name, 
            Formatter::ptr formatter,
            std::vector<LogSink::ptr> &sinks, 
            LogLevel::value level = LogLevel::value::DEBUG): 
            Logger(name, formatter, sinks, level){ 
            // 输出创建成功提示
            std::cout << LogLevel::toString(level) << " 同步日志器: " << name << "创建成功...\n";
        }

    private:
        /**
         * @brief 同步日志输出实现
         * @param msg 格式化后的日志字符串
         */
        virtual void logIt(const std::string &msg) {
            std::unique_lock<std::mutex> lock(_mutex);  // 加锁保证线程安全
            if (_sinks.empty()) { return ; }            // 无输出目标则直接返回
            // 遍历所有输出目标，写入日志
            for (auto &it : _sinks) {
                it->log(msg.c_str(), msg.size());
            }
        }
};

/**
 * @brief 异步日志器实现类
 * 特点：日志输出操作由后台线程处理，调用线程不阻塞
 */
class AsyncLogger : public Logger {
    public:
        using ptr = std::shared_ptr<AsyncLogger>;  // 异步日志器智能指针

        /**
         * @brief 构造函数
         * 参数含义同Logger基类
         */
        AsyncLogger(const std::string &name, 
            Formatter::ptr formatter, 
            std::vector<LogSink::ptr> &sinks, 
            LogLevel::value level = LogLevel::value::DEBUG): 
            Logger(name, formatter, sinks, level),
            // 初始化异步循环器，绑定后台日志处理函数
            _looper(std::make_shared<AsyncLooper>(std::bind(&AsyncLogger::backendLogIt, this, std::placeholders::_1))) {
            // 输出创建成功提示
            std::cout << LogLevel::toString(level) << "异步日志器: " << name << "创建成功...\n";
        }

    protected:
        /**
         * @brief 异步日志输出实现(前台)
         * 仅将日志消息放入后台队列，不实际输出
         * @param msg 格式化后的日志字符串
         */
        virtual void logIt(const std::string &msg) {
            _looper->push(msg);  // 将日志消息推入异步循环器的缓冲区
        }

        /**
         * @brief 后台日志处理函数(由异步线程调用)
         * @param msg 日志缓冲区
         */
        void backendLogIt(Buffer &msg) {
            if (_sinks.empty()) { return; }  // 无输出目标则直接返回
            // 遍历所有输出目标，写入日志
            for (auto &it : _sinks) {
                it->log(msg.begin(), msg.readAbleSize());
            }
        }

    protected:
        AsyncLooper::ptr _looper;  // 异步循环器(管理后台线程和消息队列)
};

/**
 * @brief 本地日志器构建器(不注册到全局管理器)
 */
class LocalLoggerBuilder: public Logger::Builder {
    public:
        /**
         * @brief 构建日志器实例(本地使用，不加入全局管理器)
         * @return 日志器智能指针
         */
        virtual Logger::ptr build() {
            if (_logger_name.empty()) {  // 检查日志器名称是否为空
                std::cout << "日志器名称不能为空！！";
                abort();  // 名称为空则终止程序
            }
            // 若未设置格式化器，使用默认格式
            if (_formatter.get() == nullptr) {
                std::cout << "当前日志器：" << _logger_name << " 未检测到日志格式，默认设置为[ %d{%H:%M:%S}%T%t%T[%p]%T[%c]%T%f:%l%T%m%n ]!\n";
                _formatter = std::make_shared<Formatter>();
            }
            // 若未设置输出目标，默认使用标准输出
            if (_sinks.empty()) {
                std::cout << "当前日志器：" << _logger_name << " 未检测到落地方向，默认设置为标准输出!\n";
                _sinks.push_back(std::make_shared<StdoutSink>());
            }
            Logger::ptr lp;
            // 根据类型创建同步/异步日志器
            if (_logger_type == Logger::Type::LOGGER_ASYNC) {
                lp = std::make_shared<AsyncLogger>(_logger_name, _formatter, _sinks, _level);
            }else {
                lp = std::make_shared<SyncLogger>(_logger_name, _formatter, _sinks, _level);
            }
            return lp;
        }
};


/**
 * @brief 日志器管理器，负责全局日志器的注册和管理
 * 单例模式，确保全局唯一实例
 */
class loggerManager{
    private:
        std::mutex _mutex;  // 同步锁(保护多线程操作)
        Logger::ptr _root_logger;  // 根日志器(默认日志器)
        // 日志器映射表(名称->日志器实例)
        std::unordered_map<std::string, Logger::ptr> _loggers;

    private:
        /**
         * @brief 私有构造函数(单例模式)
         * 初始化根日志器
         */
        loggerManager(){ 
            // 创建本地日志器构建器，初始化根日志器
            std::unique_ptr<LocalLoggerBuilder> slb(new LocalLoggerBuilder());
            slb->buildLoggerName("root");  // 根日志器名称固定为"root"
            slb->buildLoggerType(Logger::Type::LOGGER_SYNC);  // 默认同步模式
            _root_logger = slb->build();
            _loggers.insert(std::make_pair("root", _root_logger));  // 加入映射表
        }

        // 禁止拷贝构造和赋值操作(单例模式保证)
        loggerManager(const loggerManager&) = delete;
        loggerManager &operator=(const loggerManager&) = delete;

    public:
        /**
         * @brief 获取单例实例
         * @return 日志器管理器引用
         */
        static loggerManager& getInstance() {
            static loggerManager lm;  // 局部静态变量保证线程安全的单例
            return lm;
        }

        /**
         * @brief 检查指定名称的日志器是否存在
         * @param name 日志器名称
         * @return 是否存在(true/false)
         */
        bool hasLogger(const std::string &name)  {
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _loggers.find(name);
            return it != _loggers.end();
        }

        /**
         * @brief 向全局管理器添加日志器
         * @param name 日志器名称
         * @param logger 日志器实例
         */
        void addLogger(const std::string &name, const Logger::ptr logger) {
            std::unique_lock<std::mutex> lock(_mutex);
            _loggers.insert(std::make_pair(name, logger));
        }

                /**
         * @brief 获取指定名称的日志器
         * @param name 日志器名称
         * @return 日志器智能指针(若不存在则返回空指针)
         */
        Logger::ptr getLogger(const std::string &name) {
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _loggers.find(name);
            if (it == _loggers.end()) {
                return Logger::ptr();
            }
            return it->second;
        }

        /**
         * @brief 获取根日志器
         * @return 根日志器智能指针
         */
        Logger::ptr rootLogger() {
            std::unique_lock<std::mutex> lock(_mutex);
            return _root_logger;
        }
};

/**
 * @brief 全局日志器构建器(注册到全局管理器)
 * 构建的日志器会自动添加到loggerManager中供全局使用
 */
class GlobalLoggerBuilder: public Logger::Builder {
    public:
        /**
         * @brief 构建日志器实例并注册到全局管理器
         * @return 日志器智能指针
         */
        virtual Logger::ptr build() {
            if (_logger_name.empty()) {  // 检查日志器名称是否为空
                std::cout << "日志器名称不能为空！！";
                abort();  // 名称为空则终止程序
            }
            // 确保日志器名称全局唯一(已存在则断言失败)
            assert(loggerManager::getInstance().hasLogger(_logger_name) == false);
            
            // 若未设置格式化器，使用默认格式
            if (_formatter.get() == nullptr) {
                std::cout << "当前日志器：" << _logger_name << " 未检测到日志格式，默认设置为[ %d{%H:%M:%S}%T%t%T[%p]%T[%c]%T%f:%l%T%m%n ]!\n";
                _formatter = std::make_shared<Formatter>();
            }
            
            // 若未设置输出目标，默认使用标准输出
            if (_sinks.empty()) {
                std::cout << "当前日志器：" << _logger_name << " 未检测到落地方向，默认设置为标准输出!\n";
                _sinks.push_back(std::make_shared<StdoutSink>());
            }
            
            // 根据类型创建同步/异步日志器
            Logger::ptr lp;
            if (_logger_type == Logger::Type::LOGGER_ASYNC) {
                lp = std::make_shared<AsyncLogger>(_logger_name, _formatter, _sinks, _level);
            } else {
                lp = std::make_shared<SyncLogger>(_logger_name, _formatter, _sinks, _level);
            }
            
            // 将新创建的日志器注册到全局管理器
            loggerManager::getInstance().addLogger(_logger_name, lp);
            return lp;
        }
};

}  // namespace zdflog

#endif  // __M_LOG_H__